package interactive
{
	import flash.display.Stage;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import interactive.states.ClickState;
	import interactive.states.ClickTouchState;
	import interactive.states.IGestureState;
	import interactive.states.LeaveState;
	import interactive.states.MoveState;
	import interactive.states.NormalState;
	import interactive.states.TouchState;
	import interactive.states.WaitClickState;
	import interactive.states.WaitDoubleClickState;
	import interactive.states.WaitHandState;
	import interactive.states.WaitStopMoveState;
	
	import utils.pool.ObjectPool;
	
	import worlds.BaseWorld;
	
	public class GestureManager
	{
		public static const LEAVE_DELAY				: int = 80;		// 判定单击的最小离开延迟毫秒数，少于这个时间将不会判定为离开
		public static const CLICK_LEAVE_DELAY		: int = 30;		// 判定点击成功离开的最小延迟毫秒数，多于这个时间将被判定点击成功
		public static const DOUBLE_CLICK_DELAY		: int = 200;	// 判定单击变为双击的最大延迟毫秒数，多于这个时间将不会判定为双击
		public static const HAND_DELAY_MAX			: int = 150;	// 判定为手势移动的最大移动毫秒数，多于这个时间的将会被判定为拖曳
		public static const HAND_DISTANCE_MIN		: int = 20;		// 判定为手势移动的最小移动像素，少于这个距离的将会被判定为没有移动
		public static const HAND_DISTANCE_MAX		: int = 500;	// 判定为手势移动的最大移动像素，多于这个距离的将会被判定为移动
		
		public var normalState						: NormalState;
		public var touchState						: TouchState;
		public var waitClickState					: WaitClickState;
		public var waitHandState					: WaitHandState;
		public var clickState						: ClickState;
		public var clickTouchState					: ClickTouchState;
		public var waitDoubleClickState				: WaitDoubleClickState;
		public var moveState						: MoveState;
		public var waitStopMoveState				: WaitStopMoveState;
		public var leaveState						: LeaveState;
		
		private var _touchPoint						: Point = new Point();
		private var _currentState					: IGestureState;
		
		private var _downTarget						: Object;
		private var _upTarget						: Object;
		private var _moveTarget						: Object;
		
		private var _downDispatcher					: Object;
		private var _upDispatcher					: Object;
		private var _moveDispatcher					: Object;
		
		public function get touchX():Number {
			return _touchPoint.x;
		}
		public function get touchY():Number {
			return _touchPoint.y;
		}
		public function get downTarget():Object {
			return _downTarget;
		}
		public function get upTarget():Object {
			return _upTarget;
		}
		public function get moveTarget():Object {
			return _moveTarget;
		}
		public function get downDispatcher():Object {
			return _downDispatcher;
		}
		public function get upDispatcher():Object {
			return _upDispatcher;
		}
		public function get moveDispatcher():Object {
			return _moveDispatcher;
		}
		
		public function GestureManager()
		{
		}
		public function init():void {
			// 设置各种状态
			normalState = new NormalState();
			touchState = new TouchState();
			waitClickState = new WaitClickState();
			waitHandState = new WaitHandState();
			clickState = new ClickState();
			clickTouchState = new ClickTouchState();
			waitDoubleClickState = new WaitDoubleClickState();
			moveState = new MoveState();
			waitStopMoveState = new WaitStopMoveState();
			leaveState = new LeaveState();
			// 默认当前状态为普通状态
			var point:Point = ObjectPool.pop(Point) as Point;
			switchState(normalState, point);
			ObjectPool.push(point);
			
			var stage:Stage = BaseWorld.getInstance().stage;
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		}
		private function mouseDownHandler(event:MouseEvent):void {
			if(_currentState == normalState) {
				_touchPoint.x = event.stageX;
				_touchPoint.y = event.stageY;
				_downTarget = event.target;
				_downDispatcher = BaseWorld.getInstance().getActiveContainer();
			}
			var point:Point = ObjectPool.pop(Point) as Point;
			point.x = event.stageX;
			point.y = event.stageY;
			_currentState.touch(this, point);
			ObjectPool.push(point);
		}
		private function mouseUpHandler(event:MouseEvent):void {
			var point:Point = ObjectPool.pop(Point) as Point;
			point.x = event.stageX;
			point.y = event.stageY;
			_upTarget = event.target;
			_upDispatcher = BaseWorld.getInstance().getActiveContainer();
			_currentState.leave(this, point);
			ObjectPool.push(point);
		}
		private function mouseMoveHandler(event:MouseEvent):void {
			var point:Point = ObjectPool.pop(Point) as Point;
			point.x = event.stageX;
			point.y = event.stageY;
			_moveTarget = event.target;
			_moveDispatcher = BaseWorld.getInstance().getActiveContainer();
			_currentState.move(this, point);
			ObjectPool.push(point);
		}
		
		/**
		 *
		 * 返回原有状态 
		 * @param state 退回的状态
		 * @param point 点信息
		 * 
		 */		
		public function backToState(state:IGestureState, point:Point):void {
			if(_currentState != null) _currentState.switchOut(this, point);
			_currentState = state;
			if(_currentState != null) _currentState.backIn(this, point);
		}
		/**
		 *
		 * 切换状态 
		 * @param state 切换到的状态
		 * @param point 点信息
		 * 
		 */		
		public function switchState(state:IGestureState, point:Point):void {
			if(_currentState != null) _currentState.switchOut(this, point);
			_currentState = state;
			if(_currentState != null) _currentState.switchIn(this, point);
		}
		/**
		 *
		 * 根据传入的点与触摸时的点进行比较判断其手势移动方向并返回 
		 * @param point 需要与触摸时的点进行比较的点
		 * @return 手势方向
		 * 
		 */		
		public function getHandType(point:Point):int {
			// 同一个点，没有移动
			if(point.x == _touchPoint.x && point.y == _touchPoint.y) {
				return HandType.HAND_NONE;
			}
			// 纯上下移动
			if(point.x == _touchPoint.x) {
				if(point.y > _touchPoint.y) return HandType.HAND_DOWN;
				else return HandType.HAND_UP;
			}
			var angle:Number = Math.atan((point.y - _touchPoint.y) / (point.x - _touchPoint.x));
			if(point.x - _touchPoint.x > 0) {
				// 计算y变化为正数时的正切值
				if(angle < - Math.PI / 3) return HandType.HAND_UP;
				else if(angle >= Math.PI / 3) return HandType.HAND_DOWN;
				else return HandType.HAND_RIGHT;
			} else {
				// 计算y变化为负数时的正切值
				if(angle < - Math.PI / 3) return HandType.HAND_DOWN;
				else if(angle >= Math.PI / 3) return HandType.HAND_UP;
				else return HandType.HAND_LEFT;
			}
		}
	}
}